home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-06-16 | 11.9 KB | 388 lines | [TEXT/MMCC] |
- //
- // Application: CustomGetFolder
- //
- // Description: This demonstrates a CustomGetDialog for selecting a folder or volume.
- // This sample is based on Steve Falkenburg's sample of a few yesrs back,
- // the sample code in InsideMac:Files, and the Human Interface Guidelines
- // It also has Baloon Help strings for the Select button
- //
- // Programmer: David Hayward
- // Developer Technical Support
- // Apple Computer, Inc.
- //
- // Environment: Metrowerks C version 6, Universal Interfaces 2.0
- //
- // History: 4/20/95
- // first draft
- // 5/12/95
- // updated project for Metrowerks
- //
-
-
- #include <Dialogs.h>
- #include <Fonts.h>
- #include <Types.h>
- #include <Gestalt.h>
- #include <Resources.h>
- #include <Controls.h>
- #include <StandardFile.h>
- #include <TextUtils.h>
- #include <Files.h>
- #include <Folders.h>
- #include <Traps.h>
- #include <Script.h>
- #include <Aliases.h>
-
- #include "InitMac.h"
-
-
- /**\
- |**| ==============================================================================
- |**| DEFINES
- |**| ==============================================================================
- \**/
- #define ReplyDialogID 128
- #define ReplyDialogQuitItem 1
- #define ReplyDialogAgainItem 2
-
- #define CustomGetFolderDialogID 129
- #define kSelectItem 13
-
- #define kSelectStrRsrc 130
- #define kDeskStrRsrc 131
-
- #define kCanSelectDesktop true
-
-
- /**\
- |**| ==============================================================================
- |**| GLOBALS
- |**| ==============================================================================
- \**/
- FSSpec gDeskFolderSpec;
- Str255 gSelectString = "\pSelect"; // hardcode default value in case res load fails
- Str63 gDesktopFName = "\pDesktop"; // hardcode default value in case res load fails
-
-
- /**\
- |**| ==============================================================================
- |**| FUNCTION PROTOTYPES
- |**| ==============================================================================
- \**/
- void AppendStrToStr ( StringPtr dst, StringPtr src, unsigned char maxDstLen );
- void GetStringPtr ( short id, StringPtr dest ) ;
- OSErr CustomGetFolder ( StandardFileReply *reply ) ;
- pascal short MyDlgHook ( short item, DialogPtr theDlg, Ptr userData ) ;
- pascal Boolean MyFilterAllFiles ( CInfoPBPtr pb, Ptr myDataPtr ) ;
- void SetSelectButtonName ( FSSpec *spec, DialogPtr theDlg ) ;
- Boolean SameFile ( FSSpec *spec1, FSSpec *spec2 ) ;
- OSErr GetDeskFolderSpec ( FSSpec *spec ) ;
- OSErr MakeCanonFSSpec ( FSSpec *spec ) ;
- short MyAlert ( StandardFileReply *reply ) ;
-
-
- /*------------------------------------------------------------------------------*\
- AppendStrToStr()
- *------------------------------------------------------------------------------*
- utility function to append one string to another
- this function should be improved to handle errors
- \*------------------------------------------------------------------------------*/
- void AppendStrToStr ( StringPtr dst, StringPtr src, unsigned char maxDstLen)
- {
- short offset = dst[0]+1;
- short size = src[0];
-
- if ( dst[0] + src[0] > maxDstLen) // make sure were not too big
- size = maxDstLen - dst[0]; // you should return a warning here
- BlockMove( src+1, dst+offset, size);
- dst[0] += size;
- }
-
-
- /*------------------------------------------------------------------------------*\
- GetStringPtr()
- *------------------------------------------------------------------------------*
- utility function to get a string from a 'STR ' resource
- this function should be improved to handle errors
- \*------------------------------------------------------------------------------*/
- void GetStringPtr ( short id, StringPtr dest )
- {
- StringHandle strHndl ;
-
- strHndl = GetString( id ) ;
- if ( ResError() == noErr && strHndl != nil )
- {
- HLock( (Handle)strHndl ) ;
- BlockMove( *strHndl, dest, (*strHndl)[0]+1) ;
- HUnlock( (Handle)strHndl ) ;
- ReleaseResource( (Handle)strHndl ) ;
- }
- }
-
-
- /* CustomGetFolder */
- OSErr CustomGetFolder ( StandardFileReply *reply )
- {
- Point where = {-1,-1}; /* center dialog on main screen */
- OSErr err;
- Boolean targetIsFolder,wasAliased;
-
- /* initialize global data */
- GetDeskFolderSpec( &gDeskFolderSpec );
- GetStringPtr( kSelectStrRsrc, gSelectString ) ;
- GetStringPtr( kDeskStrRsrc, gDesktopFName ) ;
-
- CustomGetFile( MyFilterAllFiles, /* file filter proc */
- -1, /* number of file types */
- nil, /* array of file types */
- reply, /* the StandardFileReply structure */
- CustomGetFolderDialogID, /* the dialog's ID */
- where, /* position of dialog on screen */
- (DlgHookYDProcPtr)MyDlgHook,/* the Dialog Hook procedure */
- nil, /* no modal dialog filterProc */
- nil, /* no activeListPtr */
- nil, /* no activateProc */
- reply /* yourDataPtr: pass reply in so that */
- ); /* MyDlgHook() can access current info */
-
- if ( !reply->sfGood ) /* if the user hit cancel button */
- return noErr ; /* then nothing more to do so return */
-
-
- // if its an alias
- {
- err = ResolveAliasFile( &(reply->sfFile),
- true,
- &targetIsFolder,
- &wasAliased);
- if (err) return err ;
- }
-
-
- // if is not a directory or volume
- if ( !reply->sfIsFolder && !reply->sfIsVolume )
- {
- FSSpec tempSpec;
- CInfoPBRec infoPB;
- Boolean IsDirectory;
-
- tempSpec = reply->sfFile;
- if (tempSpec.name[0] != '\0') return; //err
-
- infoPB.dirInfo.ioNamePtr = tempSpec.name;
- infoPB.dirInfo.ioVRefNum = tempSpec.vRefNum;
- infoPB.dirInfo.ioDrDirID = tempSpec.parID;
- infoPB.dirInfo.ioFDirIndex = -1;
-
- err = PBGetCatInfo( &infoPB, false );
- if (err) return err ;
-
- tempSpec.parID = infoPB.dirInfo.ioDrParID ;
-
- // make sure that it's a directory
- IsDirectory = (infoPB.dirInfo.ioFlAttrib & 0x10) ;
- if ( !IsDirectory ) return; //err
-
- reply->sfFile = tempSpec ;
- reply->sfScript = infoPB.dirInfo.ioDrFndrInfo.frScript ;
- reply->sfFlags = infoPB.dirInfo.ioDrUsrWds.frFlags ;
- reply->sfIsFolder = (tempSpec.parID == 1) ? (0x00) : (0xFF) ;
- reply->sfIsVolume = (tempSpec.parID == 1) ? (0xFF) : (0x00) ; ;
- }
-
- }
-
-
- pascal short MyDlgHook ( short item, DialogPtr theDlg, Ptr userData )
- {
- StandardFileReply *reply;
- FSSpec curSpec;
- OSType refCon;
- static FSSpec lastSpec; /* remember and lastSpec so that we */
- /* don't update Select button needlessly */
-
- refCon = GetWRefCon(theDlg);
- if (refCon!=sfMainDialogRefCon)
- return item;
-
- reply = (StandardFileReply*)userData;
-
- if (item == sfHookFirstCall) /* if the dialog is just about to appear */
- lastSpec.vRefNum = -9999; /* init to ridiculous value */
-
- if (item == sfHookNullEvent) /* if we got a NullEvent */
- {
- if ( !SameFile( &(reply->sfFile), &lastSpec) )
- {
- curSpec = reply->sfFile ;
- MakeCanonFSSpec( &curSpec );
- SetSelectButtonName( &curSpec, theDlg);
- lastSpec = reply->sfFile ;
- }
- }
-
- if ( item==kSelectItem)
- item = sfItemOpenButton;
-
- return item;
- }
-
-
- /*------------------------------------------------------------------------------*\
- MyFilterAllFiles()
- *------------------------------------------------------------------------------*
- A file filter proc that removes everything but directories from the
- CustomGetFile list. This means that only Folders, Volumes, or Aliases of
- Folders or Volumes will appear in the list.
- \*------------------------------------------------------------------------------*/
- pascal Boolean MyFilterAllFiles ( CInfoPBPtr pb, Ptr myDataPtr )
- {
- if (pb->hFileInfo.ioFlAttrib & (1<<4)) /* file is a directory */
- return false;
- return true;
- }
-
-
- /*------------------------------------------------------------------------------*\
- SetSelectButtonName()
- *------------------------------------------------------------------------------*
- This routine gets the "Select" button from the CustomGetFile dialog and
- the filename string from the FSSpec parameter. It set the buttons name
- to Select “filename”, truncating the filemane if needed. The button is
- dimmed if kCanSelectDesktop==false and the FSSpec=the desktop folder.
- \*------------------------------------------------------------------------------*/
- void SetSelectButtonName ( FSSpec *spec, DialogPtr theDlg )
- {
- short iType;
- Handle iHndl;
- Rect iRect;
- Str63 selNameTrunc = "\p";
- Str255 btnName = "\p";
- short btnWidth;
- Boolean hilited = true;
-
- if ( SameFile( spec, &gDeskFolderSpec) )
- {
- AppendStrToStr( selNameTrunc, gDesktopFName, 63 ) ;
- hilited = kCanSelectDesktop;
- }
- else
- AppendStrToStr( selNameTrunc, spec->name, 63 ) ;
-
-
- GetDItem(theDlg,kSelectItem,&iType,&iHndl,&iRect);
-
- /* truncate select name to fit in button */
- btnWidth = iRect.right - iRect.left;
- btnWidth -= StringWidth(gSelectString);
- btnWidth -= StringWidth("\p “” ");
- TruncString(btnWidth, selNameTrunc, smTruncMiddle);
-
- /* build button name string */
- AppendStrToStr( btnName, gSelectString, 255 ) ;
- AppendStrToStr( btnName, "\p “", 255) ;
- AppendStrToStr( btnName, selNameTrunc, 255) ;
- AppendStrToStr( btnName, "\p”", 255) ;
-
- SetCTitle((ControlRef)iHndl, btnName);
-
- if (hilited)
- HiliteControl((ControlRef)iHndl,0);
- else
- HiliteControl((ControlRef)iHndl,255);
- }
-
-
- /*------------------------------------------------------------------------------*\
- SameFile()
- *------------------------------------------------------------------------------*
- Compares to FSSpec records to seeif there're the same.
- \*------------------------------------------------------------------------------*/
- Boolean SameFile ( FSSpec *spec1, FSSpec *spec2 )
- {
- if (spec1->vRefNum != spec2->vRefNum)
- return false;
- if (spec1->parID != spec2->parID)
- return false;
- if ( !EqualString( spec1->name, spec2->name, false, true ) )
- return false;
- return true;
- }
-
-
- /*------------------------------------------------------------------------------*\
- GetDeskFolderSpec()
- *------------------------------------------------------------------------------*
- Returns a FSSpec record for the Desktop folder on the boot volume.
- \*------------------------------------------------------------------------------*/
- OSErr GetDeskFolderSpec ( FSSpec *spec )
- {
- OSErr err;
-
- spec->name[0] = '\0';
- err = FindFolder( kOnSystemDisk,
- kDesktopFolderType,
- kDontCreateFolder,
- &spec->vRefNum,
- &spec->parID);
- if (err) return err;
- return MakeCanonFSSpec( spec );
- }
-
-
- /*------------------------------------------------------------------------------*\
- MakeCanonFSSpec()
- *------------------------------------------------------------------------------*
- Given a FSSpec record, convert it to the connonical format with
- file's vRefNum, parrent dirID, and name.
- \*------------------------------------------------------------------------------*/
- OSErr MakeCanonFSSpec ( FSSpec *spec )
- {
- OSErr err ;
-
- err = FSMakeFSSpec( spec->vRefNum,
- spec->parID,
- spec->name,
- spec ) ;
- return noErr ;
- }
-
-
- /*------------------------------------------------------------------------------*\
- MyAlert()
- *------------------------------------------------------------------------------*
- output vital stats of the StandardFileReply to an Alert box
- \*------------------------------------------------------------------------------*/
- short MyAlert ( StandardFileReply *reply )
- {
- Str255 goodStr, replStr ;
-
- NumToString( (long)reply->sfGood, goodStr ) ;
- NumToString( (long)reply->sfReplacing, replStr ) ;
- ParamText( goodStr, replStr, reply->sfFile.name, nil ) ;
- return NoteAlert( ReplyDialogID, nil );
- }
-
-
- /*------------------------------------------------------------------------------*\
- main()
- *------------------------------------------------------------------------------*
- initialize mamagers and the keep doing
- CustomGetFolder until the user has had enough
- \*------------------------------------------------------------------------------*/
- void main ( void )
- {
- StandardFileReply reply;
- Point where = {-1,-1}; /* center dialog on main screen */
-
- InitToolBox(2) ;
-
- do
- {
- CustomGetFolder( &reply );
- }
- while (MyAlert(&reply)==ReplyDialogAgainItem); /* repeat until user has had enough */
- }
-
-
-